﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Configuration;
using System.Windows.Data;
using System.Windows.Markup;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Media;

namespace CorpAbreu.Common.BaseClasses
{
    public class ValidationRules
    {
        /// <summary>
        /// Receives a parent and check if all the children are valid
        /// </summary>
        /// <param name="parent"></param>
        /// <returns>If the controls are valid</returns>
        public bool IsValid(DependencyObject parent)
        {
            // Validate all the bindings on the parent 
            bool valid = true;
            LocalValueEnumerator localValues = parent.GetLocalValueEnumerator();
            while (localValues.MoveNext())
            {
                LocalValueEntry entry = localValues.Current;
                if (BindingOperations.IsDataBound(parent, entry.Property))
                {
                    Binding binding = BindingOperations.GetBinding(parent, entry.Property);
                    foreach (ValidationRule rule in binding.ValidationRules)
                    {
                        ValidationResult result = rule.Validate(parent.GetValue(entry.Property), null);
                        if (!result.IsValid)
                        {
                            BindingExpression expression = BindingOperations.GetBindingExpression(parent, entry.Property);
                            System.Windows.Controls.Validation.MarkInvalid(expression, new ValidationError(rule, expression, result.ErrorContent, null));
                            valid = false;
                        }
                    }
                }
            }

            // Validate all the bindings on the children 
            for (int i = 0; i != VisualTreeHelper.GetChildrenCount(parent); ++i)
            {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);
                if (!IsValid(child)) { valid = false; }
            }

            return valid;
        } 
    }

    /// <summary>
    /// Convert Validation errors to present in form
    /// </summary>
    [ValueConversion(typeof(ReadOnlyObservableCollection<ValidationError>), typeof(string))]
    public class ValidationErrorsToStringConverter : MarkupExtension, IValueConverter
    {
        public ValidationErrorsToStringConverter()
        {
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return new ValidationErrorsToStringConverter();
        }

        public object Convert(object value, Type targetType, object parameter,
            CultureInfo culture)
        {
            ReadOnlyObservableCollection<ValidationError> errors =
                value as ReadOnlyObservableCollection<ValidationError>;

            if (errors == null)
            {
                return string.Empty;
            }

            return string.Join("\n", (from e in errors
                                      select e.ErrorContent as string).ToArray());
        }

        public object ConvertBack(object value, Type targetType, object parameter,
            CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    /// <summary>
    /// Validation rule for emails
    /// </summary>
    public class EmailValidationRule : ValidationRule
    {
        private string _pattern;
        private Regex _regex;

        public string Pattern
        {
            get { return _pattern; }
            set
            {
                _pattern = value;
                _regex = new Regex(_pattern, RegexOptions.IgnoreCase);
            }
        }

        public EmailValidationRule()
        {
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            if ((String)value != String.Empty)
            {
                if (value == null || !_regex.Match(value.ToString()).Success)
                {
                    return new ValidationResult(false, ConfigurationManager.AppSettings["emailValidationMsg"].ToString());
                }
                else
                {
                    return new ValidationResult(true, null);
                }
            }
            else
            {
                return new ValidationResult(true, null);
            }
        }
    }

    /// <summary>
    /// Validation rule for empty fields
    /// </summary>
    public class EmptyFieldValidation : ValidationRule
    {
        public EmptyFieldValidation()
        {
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            if ((String)value != String.Empty)
            {
                return new ValidationResult(true, null);
            }
            else
            {
                return new ValidationResult(false, ConfigurationManager.AppSettings["emptyFieldValidationMsg"].ToString());
            }
        }
    }

    /// <summary>
    /// Validation rule for empty selection in Combobox
    /// </summary>
    public class EmptyComboboxValidation : ValidationRule
    {
        public EmptyComboboxValidation()
        {
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            try
            {
                if (((String)value != "\0" || (String)value != "0") && value != null)
                {
                    return new ValidationResult(true, null);
                }
                else
                {
                    return new ValidationResult(false, ConfigurationManager.AppSettings["emptyFieldValidationMsg"].ToString());
                }
            }
            catch
            {
                return new ValidationResult(true, null);
            }
            
        }

    }
 
}
